package com.informatics.polymer.server;

import java.net.URISyntaxException;
import java.net.URL;

import nu.xom.Attribute;
import nu.xom.Document;
import nu.xom.Element;

import org.semanticweb.owl.apibinding.OWLManager;
import org.semanticweb.owl.model.OWLAnnotation;
import org.semanticweb.owl.model.OWLClass;
import org.semanticweb.owl.model.OWLDescription;
import org.semanticweb.owl.model.OWLOntology;
import org.semanticweb.owl.model.OWLOntologyChangeException;
import org.semanticweb.owl.model.OWLOntologyCreationException;
import org.semanticweb.owl.model.OWLOntologyManager;
import org.semanticweb.owl.vocab.OWLRDFVocabulary;

/**
 * Class to convert a Web Ontology Language (OWL) file into XML.
 * 
 * @author ed
 * @version 1.0
 */
public class OWL2XMLConverter {
	private static final String CLASS = "owlClass";
	private static final String URI = "uri";
	private static final String LABEL = "label";

	/**
	 * 
	 * @param resource
	 *            - URL of the OWL file.
	 * @return XOM Document.
	 * @throws OWLOntologyCreationException
	 * @throws OWLOntologyChangeException
	 */
	public Document convert(URL resource) throws OWLOntologyCreationException,
			OWLOntologyChangeException {
		OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
		try {
			OWLOntology ontology = manager.loadOntologyFromPhysicalURI(resource
					.toURI());
			OWLClass thing = manager.getOWLDataFactory().getOWLThing();
			Element root = toXML(thing, ontology);
			Document doc = new Document(root);
			addChildren(thing, ontology, root, 100);
			return doc;
		} catch (URISyntaxException e) {
			throw new RuntimeException("URL mysteriously not a URI!", e);
		}

	}

	/**
	 * 
	 * @param cl
	 *            - The OWL class.
	 * @param ontology
	 *            - OWL ontology.
	 * @param el
	 *            - XOM Element.
	 * @param depthStop
	 *            - Maximum depth.
	 */
	private void addChildren(OWLClass cl, OWLOntology ontology, Element el,
			int depthStop) {
		if (depthStop < 1) {
			throw new RuntimeException("Recursion error - gone too far");
		}
		for (OWLDescription description : cl.getSubClasses(ontology)) {
			OWLClass child = (OWLClass) description;
			Element childEl = toXML(child, ontology);
			el.appendChild(childEl);
			addChildren(child, ontology, childEl, depthStop--);
		}
	}

	/**
	 * Converts element to XML.
	 * 
	 * @param cl
	 *            - OWLClass to convert.
	 * @param ontology
	 *            - OWL ontology containing the classes.
	 * @return
	 */
	private Element toXML(OWLClass cl, OWLOntology ontology) {
		Element el = new Element(CLASS);
		el.addAttribute(new Attribute(URI, cl.getURI().toString()));
		StringBuilder sb = new StringBuilder();
		for (OWLAnnotation<OWLClass> annotation : cl.getAnnotations(ontology,
				OWLRDFVocabulary.RDFS_LABEL.getURI())) {
			sb.append(annotation.getAnnotationValueAsConstant().getLiteral());
		}
		el.addAttribute(new Attribute(LABEL, sb.toString()));
		return el;
	}

}
